use tauri::{command, Manager, AppHandle};
use serde::{Serialize, Deserialize};
use serde_json::{json, Value};
use std::fs;
use std::time::{SystemTime, UNIX_EPOCH};
use reqwest;
use tokio::time::{self, Duration};

// 令牌缓存数据结构
#[derive(Debug, Serialize, Deserialize)]
struct TokenCache {
    access_token: String,
    expires_at: u64,
    refresh_token: String,
}

/// 深度账号绑定（OAuth2规范实现）
#[command]
pub async fn bind_deepin_account(
    handle: AppHandle,
    code: String
) -> Result<String, String> {
    let params = [
        ("client_id", "deepin_store_client_v3"),
        ("code", &code),
        ("grant_type", "authorization_code"),
        ("redirect_uri", "deepin://auth-callback")
    ];

    // 获取令牌并处理网络错误
    let token_data = request_token(&params)
        .await
        .map_err(|e| format!("认证失败: {}", e))?;

    // 缓存令牌并处理序列化错误
    cache_token(&handle, &token_data)
        .map_err(|e| format!("缓存失败: {}", e))?;

    // 触发全局状态更新
    handle.emit_all("account-updated", json!({
        "loggedIn": true,
        "userName": token_data["user_name"].as_str().unwrap_or("")
    }))
    .map_err(|e| format!("状态通知失败: {}", e))?;

    token_data["access_token"]
        .as_str()
        .map(|s| s.to_string())
        .ok_or_else(|| "无效令牌格式".into())
}

/// 令牌获取核心方法
async fn request_token(params: &[(&str, &str)]) -> Result<Value, String> {
    reqwest::Client::new()
        .post("https://id.deepin.org/oauth2/token")
        .form(params)
        .send()
        .await
        .map_err(|e| format!("网络请求失败: {}", e))?
        .json()
        .await
        .map_err(|e| format!("响应解析失败: {}", e))
}

/// 令牌缓存管理
fn cache_token(handle: &AppHandle, token_data: &Value) -> Result<(), String> {
    let expires_in = token_data["expires_in"]
        .as_u64()
        .ok_or("有效期格式错误")?;

    let cache = TokenCache {
        access_token: token_data["access_token"]
            .as_str()
            .ok_or("缺少访问令牌")?
            .to_string(),
        expires_at: SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .map_err(|_| "系统时间错误")?
            .as_secs() + expires_in,
        refresh_token: token_data["refresh_token"]
            .as_str()
            .ok_or("缺少刷新令牌")?
            .to_string(),
    };

    // 获取缓存路径
    let cache_path = handle.path_resolver()
        .app_data_dir()
        .ok_or("无法获取应用目录")?
        .join("token.json");

    // 写入缓存文件
    fs::write(cache_path, serde_json::to_string(&cache)?)
        .map_err(|e| format!("缓存写入失败: {}", e))
}

/// 令牌自动刷新服务
#[command]
pub async fn start_token_refresher(app: AppHandle) -> Result<(), String> {
    let mut interval = time::interval(Duration::from_secs(300));
    
    loop {
        interval.tick().await;
        
        let cache = match read_cache(&app) {
            Ok(c) => c,
            Err(e) => {
                app.emit_all("token-error", json!({ "message": e })).ok();
                continue;
            }
        };

        // 提前10分钟刷新
        if SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .map_err(|_| "系统时间错误")?
            .as_secs() >= cache.expires_at - 600 
        {
            match refresh_flow(&app, &cache.refresh_token).await {
                Ok(_) => app.emit_all("token-refreshed", json!({ "success": true })).ok(),
                Err(e) => app.emit_all("token-refreshed", json!({ "success": false, "error": e })).ok(),
            }
        }
    }
}

/// 刷新令牌流程
async fn refresh_flow(app: &AppHandle, refresh_token: &str) -> Result<(), String> {
    let new_token = refresh_token(refresh_token).await?;
    let token_value = json!({
        "access_token": new_token,
        "expires_in": 3600,
        "refresh_token": refresh_token
    });
    
    cache_token(app, &token_value)
}

/// 刷新令牌实现
async fn refresh_token(refresh_token: &str) -> Result<String, String> {
    let params = [
        ("client_id", "deepin_store_client_v3"),
        ("grant_type", "refresh_token"),
        ("refresh_token", refresh_token)
    ];

    let token_data = request_token(&params).await?;
    token_data["access_token"]
        .as_str()
        .map(|s| s.to_string())
        .ok_or_else(|| "无效令牌格式".into())
}

/// 缓存读取工具
fn read_cache(app: &AppHandle) -> Result<TokenCache, String> {
    let path = app.path_resolver()
        .app_data_dir()
        .ok_or("无法获取应用目录")?
        .join("token.json");

    let data = fs::read_to_string(&path)
        .map_err(|_| "缓存读取失败")?;

    serde_json::from_str(&data)
        .map_err(|_| "缓存解析失败")
}